EFFECT_SIZES
Overview
The EFFECT_SIZES function computes standardized effect size measures for comparing two independent groups, returning both Cohen’s d and Hedges’ g. Effect sizes quantify the magnitude of the difference between groups in a standardized way, making them essential for interpreting the practical significance of research findings beyond mere statistical significance.
Cohen’s d is one of the most widely used effect size measures in behavioral and social sciences, introduced by Jacob Cohen in his foundational 1988 work Statistical Power Analysis for the Behavioral Sciences. It represents the standardized difference between two group means:
d = \frac{\bar{x}_1 - \bar{x}_2}{s_{\text{pooled}}}
where \bar{x}_1 and \bar{x}_2 are the sample means and s_{\text{pooled}} is the pooled standard deviation:
s_{\text{pooled}} = \sqrt{\frac{(n_1 - 1)s_1^2 + (n_2 - 1)s_2^2}{n_1 + n_2 - 2}}
However, Cohen’s d exhibits a small positive bias in small samples. Hedges’ g corrects for this bias by applying a correction factor, as proposed by Larry Hedges in 1981:
g = d \times \left(1 - \frac{3}{4(n_1 + n_2) - 9}\right)
This makes Hedges’ g the preferred metric for meta-analysis where combining results across studies with varying sample sizes is common.
The function interprets effect sizes using Cohen’s conventional benchmarks: values below 0.2 are considered negligible, 0.2–0.5 are small, 0.5–0.8 are medium, and values above 0.8 are large. However, these thresholds should be applied with caution, as context and domain-specific norms may warrant different interpretations.
For additional statistical methods for comparing groups, see the statsmodels weightstats module and Wikipedia’s effect size article.
This example function is provided as-is without any representation of accuracy.
Excel Usage
=EFFECT_SIZES(group_a, group_b, pooled_sd)
group_a(list[list], required): A column vector containing numerical values from the first group.group_b(list[list], required): A column vector containing numerical values from the second group.pooled_sd(bool, optional, default: true): If True (default), uses the pooled standard deviation to calculate Cohen’s d. If False, uses the standard deviation of the control group (group_b).
Returns (list[list]): 2D list with effect sizes, or error message string.
Examples
Example 1: Cohen’s d with pooled standard deviation
Inputs:
| group_a | group_b | pooled_sd |
|---|---|---|
| 1 | 2 | true |
| 2 | 3 | |
| 3 | 4 | |
| 4 | 5 |
Excel formula:
=EFFECT_SIZES({1;2;3;4}, {2;3;4;5}, TRUE)
Expected output:
| measure | value | interpretation |
|---|---|---|
| Cohen’s d | -0.7746 | medium |
| Hedge’s g | -0.6736 | medium |
Example 2: Cohen’s d using control group standard deviation
Inputs:
| group_a | group_b | pooled_sd |
|---|---|---|
| 5 | 2 | false |
| 6 | 3 | |
| 7 | 4 |
Excel formula:
=EFFECT_SIZES({5;6;7}, {2;3;4}, FALSE)
Expected output:
| measure | value | interpretation |
|---|---|---|
| Cohen’s d | 3 | large |
| Hedge’s g | 2.4 | large |
Example 3: Effect size with larger sample sizes
Inputs:
| group_a | group_b |
|---|---|
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
| 6 | 7 |
Excel formula:
=EFFECT_SIZES({1;2;3;4;5;6}, {2;3;4;5;6;7})
Expected output:
| measure | value | interpretation |
|---|---|---|
| Cohen’s d | -0.5345 | medium |
| Hedge’s g | -0.4934 | medium |
Example 4: Small effect size example
Inputs:
| group_a | group_b | pooled_sd |
|---|---|---|
| 10 | 10.5 | true |
| 11 | 11.5 | |
| 12 | 12.5 | |
| 13 | 13.5 |
Excel formula:
=EFFECT_SIZES({10;11;12;13}, {10.5;11.5;12.5;13.5}, TRUE)
Expected output:
| measure | value | interpretation |
|---|---|---|
| Cohen’s d | -0.3873 | small |
| Hedge’s g | -0.3368 | small |
Python Code
import math
def effect_sizes(group_a, group_b, pooled_sd=True):
"""
Computes effect size measures for comparing two groups.
See: https://www.statsmodels.org/stable/generated/statsmodels.stats.weightstats.DescrStatsW.html
This example function is provided as-is without any representation of accuracy.
Args:
group_a (list[list]): A column vector containing numerical values from the first group.
group_b (list[list]): A column vector containing numerical values from the second group.
pooled_sd (bool, optional): If True (default), uses the pooled standard deviation to calculate Cohen's d. If False, uses the standard deviation of the control group (group_b). Default is True.
Returns:
list[list]: 2D list with effect sizes, or error message string.
"""
def to2d(x):
return [[x]] if not isinstance(x, list) else x
def validate_group(group, name):
# Validate that group is a 2D list of numbers
if not isinstance(group, list):
return f"Invalid input: {name} must be a 2D list."
if len(group) == 0:
return f"Invalid input: {name} must not be empty."
values = []
for row in group:
if not isinstance(row, list):
return f"Invalid input: {name} must be a 2D list."
if len(row) == 0:
return f"Invalid input: {name} rows must not be empty."
for val in row:
if not isinstance(val, (int, float)):
return f"Invalid input: {name} must contain only numeric values."
if math.isnan(val) or math.isinf(val):
return f"Invalid input: {name} must contain only finite values."
values.append(float(val))
if len(values) < 2:
return f"Invalid input: {name} must have at least 2 values."
return values
def get_interpretation(d_value):
# Interpret effect size based on Cohen's benchmarks
abs_d = abs(d_value)
if abs_d < 0.2:
return "negligible"
elif abs_d < 0.5:
return "small"
elif abs_d < 0.8:
return "medium"
else:
return "large"
# Normalize inputs
group_a = to2d(group_a)
group_b = to2d(group_b)
# Validate inputs
values_a = validate_group(group_a, "group_a")
if isinstance(values_a, str):
return values_a
values_b = validate_group(group_b, "group_b")
if isinstance(values_b, str):
return values_b
if not isinstance(pooled_sd, bool):
return "Invalid input: pooled_sd must be a boolean."
# Calculate means and standard deviations using standard library
n_a = len(values_a)
n_b = len(values_b)
mean_a = sum(values_a) / n_a
mean_b = sum(values_b) / n_b
# Calculate sample standard deviations (ddof=1)
std_a = math.sqrt(sum((x - mean_a) ** 2 for x in values_a) / (n_a - 1))
std_b = math.sqrt(sum((x - mean_b) ** 2 for x in values_b) / (n_b - 1))
# Calculate Cohen's d
if pooled_sd:
# Pooled standard deviation
pooled_variance = ((n_a - 1) * std_a**2 + (n_b - 1) * std_b**2) / (n_a + n_b - 2)
sd = math.sqrt(pooled_variance)
else:
# Use control group (group_b) standard deviation
sd = std_b
if sd == 0:
return "Invalid input: standard deviation is zero, cannot compute effect size."
cohens_d = float((mean_a - mean_b) / sd)
# Calculate Hedge's g (bias correction for small samples)
correction_factor = 1 - (3 / (4 * (n_a + n_b) - 9))
hedges_g = float(cohens_d * correction_factor)
# Get interpretation
interpretation = get_interpretation(cohens_d)
# Validate outputs are finite
if math.isnan(cohens_d) or math.isinf(cohens_d):
return "Computation error: Cohen's d is not finite."
if math.isnan(hedges_g) or math.isinf(hedges_g):
return "Computation error: Hedge's g is not finite."
# Build result table
result = [
["measure", "value", "interpretation"],
["Cohen's d", cohens_d, interpretation],
["Hedge's g", hedges_g, interpretation],
]
return result